﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using Server;
using System;
using System.Text;

namespace Consumer1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("发布者确认消费端");

            WorkConsumer.ReciveMsg();
            Console.ReadLine();
        }
    }

    class WorkConsumer
    {
        private static readonly ConnectionFactory rabbitMqFactory = CommonConnectionFactory.rabbitMqFactory;

        public static void ReciveMsg()
        {

            using (IConnection conn = rabbitMqFactory.CreateConnection())
            {
                using (IModel channel = conn.CreateModel())
                {
                    string QueueName = "发布者确认队列";
                    channel.QueueDeclare(QueueName, durable: true, autoDelete: false, exclusive: false, arguments: null);
                    //字节限制，一次接收的消息数，全局/
                    //据说prefetchSize 和global这两项，rabbitmq没有实现，暂且不研究
                    channel.BasicQos(prefetchSize: 0, prefetchCount: 1, false);
                    var consumer = new EventingBasicConsumer(channel);

                    consumer.Received += (model, ea) =>
                    {
                        //Thread.Sleep(3000);
                        var msgBody = Encoding.UTF8.GetString(ea.Body.ToArray());

                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                        Console.WriteLine($@"[{msgBody}] OK");

                    };
                    //autoAck 自动确认 默认true，设置为false 则必须channel.BasicAck(**********);
                    channel.BasicConsume(queue: QueueName, autoAck: false, consumer: consumer);
                    Console.WriteLine("接收到消息");
                    Console.ReadLine();
                }
            }
        }
    }
}

//第一种：消息持久化
//RabbitMQ 的消息默认存放在内存上面，如果不特别声明设置，消息不会持久化保存到硬盘上面的，如果节点重启或者意外crash掉，消息就会丢失。

//所以就要对消息进行持久化处理。如何持久化，下面具体说明下：

//要想做到消息持久化，必须满足以下三个条件，缺一不可。

//1） Exchange 设置持久化

//2）Queue 设置持久化

//3）Message持久化发送：发送消息设置发送模式deliveryMode=2，代表持久化消息

//第二种：ACK确认机制
//多个消费者同时收取消息，比如消息接收到一半的时候，一个消费者死掉了(逻辑复杂时间太长，超时了或者消费被停机或者网络断开链接)，如何保证消息不丢？

//这个使用就要使用Message acknowledgment 机制，就是消费端消费完成要通知服务端，服务端才把消息从内存删除。

//这样就解决了，及时一个消费者出了问题，没有同步消息给服务端，还有其他的消费端去消费，保证了消息不丢的case。

//第三种：设置集群镜像模式
//我们先来介绍下RabbitMQ三种部署模式：

//1）单节点模式：最简单的情况，非集群模式，节点挂了，消息就不能用了。业务可能瘫痪，只能等待。
//2）普通模式：默认的集群模式，某个节点挂了，该节点上的消息不能用，有影响的业务瘫痪，只能等待节点恢复重启可用（必须持久化消息情况下）。
//3）镜像模式：把需要的队列做成镜像队列，存在于多个节点，属于RabbitMQ的HA方案

//为什么设置镜像模式集群，因为队列的内容仅仅存在某一个节点上面，不会存在所有节点上面，所有节点仅仅存放消息结构和元数据。
